package com.example.financechain.service.Impl;

import com.alibaba.fastjson.JSON;
import com.example.financechain.Utils.JsonData;
import com.example.financechain.Utils.UserThreadLocal;
import com.example.financechain.domain.VO.MenuVo;
import com.example.financechain.domain.entity.Menu;
import com.example.financechain.domain.entity.Role;
import com.example.financechain.mapper.MenuMapper;
import com.example.financechain.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author yy
 * @since 2023-04-13
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {


    @Autowired
    private MenuMapper menuMapper;

    @Resource
    StringRedisTemplate stringRedisTemplate;


    @Override
    public  List<MenuVo> buildmenu() {

        Role role = UserThreadLocal.get();
        Long roleId = role.getRoleId();

        List<MenuVo> buildmenulist=new ArrayList<>();

        String json = stringRedisTemplate.opsForValue().get("MENU" + role.getNickName());

        if (StringUtils.isNotBlank(json)){
            buildmenulist = JSON.parseArray(json,MenuVo.class);
            return buildmenulist;
        }

        List<Menu> menuList =menuMapper.selectMenuListByUserId(roleId);
        //List<Menu> menuList = menuService.list();
        List<MenuVo> menuVoList =new ArrayList<>();

        //System.out.println(menuList);

        for (Menu m : menuList
        ) {
            MenuVo menuVo =new MenuVo();

            menuVo.setId(m.getId());
            menuVo.setRemark("");
            menuVo.setMenuName(m.getMenuName());
            menuVo.setComponent(m.getComponent());
            menuVo.setNameZh(m.getNameZh());
            menuVo.setIconCls(m.getIconCls());
            menuVo.setPath(m.getPath());
            menuVo.setSequence(m.getSequence());
            menuVo.setParentId(m.getParentId());
            menuVo.setChildren(new ArrayList<>());

            menuVoList.add(menuVo);

        }


         buildmenulist = getChildPerms(menuVoList,0);

        Collections.sort(buildmenulist, new Comparator<MenuVo>() {
            @Override
            public int compare(MenuVo m1, MenuVo m2) {
                return m1.getSequence()-m2.getSequence();
            }
        });


        stringRedisTemplate.opsForValue().set("MENU"+role.getNickName(), JSON.toJSONString(buildmenulist),10L, TimeUnit.SECONDS);

        return buildmenulist;
    }

    public List<MenuVo> getChildPerms(List<MenuVo> list, int parentId)
    {
        List<MenuVo> returnList = new ArrayList<MenuVo>();
        for (Iterator<MenuVo> iterator = list.iterator(); iterator.hasNext();)
        {
            MenuVo t = (MenuVo) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == parentId)
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }


    private void recursionFn(List<MenuVo> list, MenuVo t)
    {
        // 得到子节点列表
        List<MenuVo> childList = getChildList(list, t);
        t.setChildren(childList);
        for (MenuVo tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }


    private List<MenuVo> getChildList(List<MenuVo> list, MenuVo t)
    {
        List<MenuVo> tlist = new ArrayList<MenuVo>();
        Iterator<MenuVo> it = list.iterator();
        while (it.hasNext())
        {
            MenuVo n = (MenuVo) it.next();
            if (n.getParentId().longValue() == t.getId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    private boolean hasChild(List<MenuVo> list, MenuVo t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}
